home *** CD-ROM | disk | FTP | other *** search
- #--
- # Copyright (c) 2002,2003 Core Security Technologies, Core SDI Inc.
- # All rights reserved.
- #
- # Unless you have express writen permission from the Copyright Holder, any
- # use of or distribution of this software or portions of it, including, but not
- # limited to, reimplementations, modifications and derived work of it, in
- # either source code or any other form, as well as any other software using or
- # referencing it in any way, may NOT be sold for commercial gain, must be
- # covered by this very same license, and must retain this copyright notice and
- # this license.
- # Neither the name of the Copyright Holder nor the names of its contributors
- # may be used to endorse or promote products derived from this software
- # without specific prior written permission.
- #
- # THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE
- # LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
- # OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND,
- # EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
- # ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU.
- # SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
- # SERVICING, REPAIR OR CORRECTION.
- #
- # IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
- # ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
- # THE SOFTWARE AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
- # GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
- # OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
- # DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR
- # A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH
- # HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- #
- # gera [at corest.com]
- #--
- # $Id: inlineegg.py,v 1.3 2004/02/05 07:57:30 hdm Exp $
-
- import struct
- import types
-
- class Variable:
- def __init__(self, offset, size = None):
- self.offset = offset
- self.size = size
-
- def value(self,delta = 0):
- return 'var%d' % (self.offset+delta)
-
- def addr(self,delta = 0):
- return 'ptr%d' % (self.offset+delta)
-
- def __add__(self,delta):
- return self.__class__(self.offset-delta,self.size and self.size-delta)
-
- def __sub__(self,delta):
- return self + -delta
-
- def startswith(self,string):
- return string == 'var'
-
- class Microprocessor:
- pass
-
- class Microx86(Microprocessor):
- # zero causes:
- # push 0, push 0x00001234, push 0x00123456, push 0x12000034
- # mov dx, 0x400
- # sub esp, 0x400
- # mov esi, [esp+0x41c]
- # mov ebx, [esp]
- # cmp eax,0
- def __init__(self):
- self._registers = ['eax','ecx','edx','ebx','esp','ebp','esi','edi']
- self.opcodes = {
- '': {
- # stack
- 'pushb':'\x6a%c',
- 'pushl':'\x68%s',
- 'pushVarb':'\xff\x74\x24%c',
- 'pushVarl':'\xff\xb4\x24%s',
- 'pushVarPtrb':'\x54\x83\x2c\x24%c', # push esp; sub $ptr, (%esp)
- 'pushVarPtrl':'\x54\x81\x2c\x24%s', # push esp; sub $ptr, (%esp)
- 'cmpbVarb':'\x83\x7c\x24%c%c', # off, val : cmpl $val, off(%esp)
- 'cmpbVarl':'\x83\xbc\x24%s%c', # off, val : cmpl $val, off(%esp)
- 'cmplVarb':'\x81\x7c\x24%c%s', # off, val : cmpl $val, off(%esp)
- 'cmplVarl':'\x81\xbc\x24%s%s', # off, val : cmpl $val, off(%esp)
- 'callVarb':'\xff\x54\x24%c',
- 'callVarl':'\xff\x94\x24%s',
- 'incVarb':'\xff\x44\x24%c',
- 'incVarl':'\xff\x84\x24%s',
- 'decVarb':'\xff\x4c\x24%c',
- 'decVarl':'\xff\x8c\x24%s',
-
-
- # jumps
- 'jmpb':'\xeb%(b)s',
- 'jmpl':'\xe9%(l)s',
- 'jmpb=':'\x74%(b)s',
- 'jmpb!=':'\x75%(b)s',
- '!=':'!=', # the oposite condition is used on ifs
- '!!=':'=',
- 'jmpb<':'\x72%(b)s',
- 'jmpb>=':'\x73%(b)s',
- '!<':'>=',
- '!>=':'<',
- },
- 'eax': {
- 'value':None,
- 'movb':'\xb0%(b)s',
- 'movw':'\x66\xb8%(w)s',
- 'movl':'\xb8%(l)s',
- 'cmpb':'\x83\xf8%(b)s',
- 'cmpl':'\x3d%(l)s',
- 'zero':'\x31\xc0',
- 'moveax':'',
- 'movebx':'\x89\xd8',
- 'movecx':'\x89\xc8',
- 'movedx':'\x89\xd0',
- 'movesi':'\x89\xf0',
- 'movedi':'\x89\xf8',
- 'movebp':'\x89\xe8',
- 'movesp':'\x89\xe0',
- 'cmpeax':'\x39\xc0',
- 'cmpebx':'\x39\xc3',
- 'cmpecx':'\x39\xc1',
- 'cmpedx':'\x39\xc2',
- 'cmpesi':'\x39\xc6',
- 'cmpedi':'\x39\xc7',
- 'cmpebp':'\x39\xc5',
- 'cmpesp':'\x39\xc4',
- 'movVarb':'\x8b\x44\x24%(b)s',
- 'movVarl':'\x8b\x84\x24%(l)s',
- 'movVarPtrb':'\x8d\x44\x24%(b)s',
- 'movVarPtrl':'\x8d\x84\x24%(l)s',
- 'subb':None,
- 'subl':None,
- 'subVarb':None,
- 'subVarl':None,
- },
- 'ebx': {
- 'value':None,
- 'movb':'\xb3%(b)s',
- 'movw':'\x66\xbb%(w)s',
- 'movl':'\xbb%(l)s',
- 'cmpb':'\x83\xfb%(b)s',
- 'cmpl':'\x81\xfb%(l)s',
- 'zero':'\x31\xdb',
- 'moveax':'\x89\xc3',
- 'movebx':'',
- 'movecx':'\x89\xcb',
- 'movedx':'\x89\xd3',
- 'movesi':'\x89\xf3',
- 'movedi':'\x89\xfb',
- 'movebp':'\x89\xeb',
- 'movesp':'\x89\xe3',
- 'cmpeax':'\x39\xd8',
- 'cmpebx':'\x39\xdb',
- 'cmpecx':'\x39\xd9',
- 'cmpedx':'\x39\xda',
- 'cmpesi':'\x39\xde',
- 'cmpedi':'\x39\xdf',
- 'cmpebp':'\x39\xdd',
- 'cmpesp':'\x39\xdc',
- 'movVarb':'\x8b\x5c\x24%(b)s',
- 'movVarl':'\x8b\x9c\x24%(l)s',
- 'movVarPtrb':'\x8d\x5c\x24%(b)s',
- 'movVarPtrl':'\x8d\x9c\x24%(l)s',
- 'subb':None,
- 'subl':None,
- 'subVarb':None,
- 'subVarl':None,
- },
- 'ecx': {
- 'value':None,
- 'movb':'\xb1%(b)s',
- 'movw':'\x66\xb9%(w)s',
- 'movl':'\xb9%(l)s',
- 'cmpb':'\x83\xf9%(b)s',
- 'cmpl':'\x81\xf9%(l)s',
- 'zero':'\x31\xc9',
- 'moveax':'\x89\xc1',
- 'movebx':'\x89\xd9',
- 'movecx':'',
- 'movedx':'\x89\xd1',
- 'movesi':'\x89\xf1',
- 'movedi':'\x89\xf9',
- 'movebp':'\x89\xe9',
- 'movesp':'\x89\xe1',
- 'cmpeax':'\x39\xc8',
- 'cmpebx':'\x39\xcb',
- 'cmpecx':'\x39\xc9',
- 'cmpedx':'\x39\xca',
- 'cmpesi':'\x39\xce',
- 'cmpedi':'\x39\xcf',
- 'cmpebp':'\x39\xcd',
- 'cmpesp':'\x39\xcc',
- 'movVarb':'\x8b\x4c\x24%(b)s',
- 'movVarl':'\x8b\x8c\x24%(l)s',
- 'movVarPtrb':'\x8d\x4c\x24%(b)s',
- 'movVarPtrl':'\x8d\x8c\x24%(l)s',
- 'subb':None,
- 'subl':None,
- 'subVarb':None,
- 'subVarl':None,
- },
- 'edx': {
- 'value':None,
- 'movb':'\xb2%(b)s',
- 'movw':'\x66\xba%(w)s',
- 'movl':'\xba%(l)s',
- 'cmpb':'\x83\xfa%(b)s',
- 'cmpl':'\x81\xfa%(l)s',
- 'zero':'\x31\xd2',
- 'moveax':'\x89\xc2',
- 'movebx':'\x89\xda',
- 'movecx':'\x89\xca',
- 'movedx':'',
- 'movesi':'\x89\xf2',
- 'movedi':'\x89\xfa',
- 'movebp':'\x89\xea',
- 'movesp':'\x89\xe2',
- 'cmpeax':'\x39\xd0',
- 'cmpebx':'\x39\xd3',
- 'cmpecx':'\x39\xd1',
- 'cmpedx':'\x39\xd2',
- 'cmpesi':'\x39\xd6',
- 'cmpedi':'\x39\xd7',
- 'cmpebp':'\x39\xd5',
- 'cmpesp':'\x39\xd4',
- 'movVarb':'\x8b\x54\x24%(b)s',
- 'movVarl':'\x8b\x94\x24%(l)s',
- 'movVarPtrb':'\x8d\x54\x24%(b)s',
- 'movVarPtrl':'\x8d\x94\x24%(l)s',
- 'subb':None,
- 'subl':None,
- 'subVarb':None,
- 'subVarl':None,
- },
- 'esi': {
- 'value':None,
- 'movb':None,
- 'movw':'\x66\xbe%(w)s',
- 'movl':'\xbe%(l)s',
- 'cmpb':'\x83\xfe%(b)s',
- 'cmpl':'\x81\xfe%(l)s',
- 'zero':'\x31\xf6',
- 'moveax':'\x89\xc6',
- 'movebx':'\x89\xde',
- 'movecx':'\x89\xce',
- 'movedx':'\x89\xd6',
- 'movesi':'',
- 'movedi':'\x89\xfe',
- 'movebp':'\x89\xee',
- 'movesp':'\x89\xe6',
- 'cmpeax':'\x39\xf0',
- 'cmpebx':'\x39\xf3',
- 'cmpecx':'\x39\xf1',
- 'cmpedx':'\x39\xf2',
- 'cmpesi':'\x39\xf6',
- 'cmpedi':'\x39\xf7',
- 'cmpebp':'\x39\xf5',
- 'cmpesp':'\x39\xf4',
- 'movVarb':'\x8b\x74\x24%(b)s',
- 'movVarl':'\x8b\xb4\x24%(l)s',
- 'movVarPtrb':'\x8d\x74\x24%(b)s',
- 'movVarPtrl':'\x8d\xb4\x24%(l)s',
- 'subb':None,
- 'subl':None,
- 'subVarb':None,
- 'subVarl':None,
- },
- 'edi': {
- 'value':None,
- 'movb':None,
- 'movw':'\x66\xbf%(w)s',
- 'movl':'\xbf%(l)s',
- 'cmpb':'\x83\xff%(b)s',
- 'cmpl':'\x81\xff%(l)s',
- 'zero':'\x31\xff',
- 'moveax':'\x89\xc7',
- 'movebx':'\x89\xdf',
- 'movecx':'\x89\xcf',
- 'movedx':'\x89\xd7',
- 'movesi':'\x89\xf7',
- 'movedi':'',
- 'movebp':'\x89\xef',
- 'movesp':'\x89\xe7',
- 'cmpeax':'\x39\xf8',
- 'cmpebx':'\x39\xfb',
- 'cmpecx':'\x39\xf9',
- 'cmpedx':'\x39\xfa',
- 'cmpesi':'\x39\xfe',
- 'cmpedi':'\x39\xff',
- 'cmpebp':'\x39\xfd',
- 'cmpesp':'\x39\xfc',
- 'movVarb':'\x8b\x7c\x24%(b)s',
- 'movVarl':'\x8b\xbc\x24%(l)s',
- 'movVarPtrb':'\x8d\x7c\x24%(b)s',
- 'movVarPtrl':'\x8d\xbc\x24%(l)s',
- 'subb':None,
- 'subl':None,
- 'subVarb':None,
- 'subVarl':None,
- },
- 'ebp': {
- 'value':None,
- 'movb':None,
- 'movw':'\x66\xbd%(w)s',
- 'movl':'\xbd%(l)s',
- 'cmpb':'\x83\xfd%(b)s',
- 'cmpl':'\x81\xfd%(l)s',
- 'zero':'\x31\xed',
- 'moveax':'\x89\xc5',
- 'movebx':'\x89\xdd',
- 'movecx':'\x89\xcd',
- 'movedx':'\x89\xd5',
- 'movesi':'\x89\xf5',
- 'movedi':'\x89\xfd',
- 'movebp':'',
- 'movesp':'\x89\xe5',
- 'cmpeax':'\x39\xe8',
- 'cmpebx':'\x39\xeb',
- 'cmpecx':'\x39\xe9',
- 'cmpedx':'\x39\xea',
- 'cmpesi':'\x39\xee',
- 'cmpedi':'\x39\xef',
- 'cmpebp':'\x39\xed',
- 'cmpesp':'\x39\xec',
- 'movVarb':'\x8b\x6c\x24%(b)s',
- 'movVarl':'\x8b\xac\x24%(l)s',
- 'movVarPtrb':'\x8d\x6c\x24%(b)s',
- 'movVarPtrl':'\x8d\xac\x24%(l)s',
- 'subb':None,
- 'subl':None,
- 'subVarb':None,
- 'subVarl':None,
- },
- 'esp': {
- 'value':None,
- 'movb':None,
- 'movw':'\x66\xbc%(w)s',
- 'movl':'\xbc%(l)s',
- 'cmpb':'\x83\xfc%(b)s',
- 'cmpl':'\x81\xfc%(l)s',
- 'zero':'\x31\xe4',
- 'moveax':'\x89\xc4',
- 'movebx':'\x89\xdc',
- 'movecx':'\x89\xcc',
- 'movedx':'\x89\xd4',
- 'movesi':'\x89\xf4',
- 'movedi':'\x89\xfc',
- 'movebp':'\x89\xec',
- 'movesp':'',
- 'cmpeax':'\x39\xe0',
- 'cmpebx':'\x39\xe3',
- 'cmpecx':'\x39\xe1',
- 'cmpedx':'\x39\xe2',
- 'cmpesi':'\x39\xe6',
- 'cmpedi':'\x39\xe7',
- 'cmpebp':'\x39\xe5',
- 'cmpesp':'\x39\xe4',
- 'movVarb':'\x8b\x64\x24%(b)s',
- 'movVarl':'\x8b\xa4\x24%(l)s',
- 'movVarPtrb':'\x8d\x64\x24%(b)s',
- 'movVarPtrl':'\x8d\xa4\x24%(l)s',
- 'subb':'\x83\xec%(b)s',
- 'subl':'\x81\xec%(l)s',
- 'subVarb':'\x2b\x64\x24%(b)s',
- 'subVarl':'\x2b\xa4\x24%(l)s',
- },
- }
-
- self.reset()
- self.stack = []
-
- def is_value(self, value):
- return type(value) == types.IntType
-
- def is_register(self, value):
- return value in self.registers()
-
- def is_variable(self, value):
- return value.startswith('var')
-
- def is_varpointer(self, value):
- return value.startswith('ptr')
-
- def is_tuple(self, value):
- return type(value) is types.TupleType or type(value) is types.ListType
-
- def reset(self):
- for i in self.opcodes.values():
- i['value'] = None
-
- def nop(self):
- return '\x90'
-
- def zero(self,reg):
- self.setValue(reg,0)
- return self.opcodes[reg]['zero']
-
- def incReg(self,reg):
- return '%c' % (0x40+self.regNum(reg))
-
- def incVar(self,var):
- offset = len(self.stack)*4 - var.offset
-
- if -128 <= offset <= 127:
- return self.opcodes['']['incVarb'] % (offset & 0xff)
- return self.opcodes['']['incVarl'] % struct.pack('<l',offset)
-
- def inc(self, operator):
- if self.is_register(operator):
- return self.incReg(operator)
- if self.is_variable(operator):
- return self.incVar(operator)
- raise Exception, ('incrementing (%s) not yet implemented' % operator)
-
- def decReg(self,reg):
- return '%c' % (0x48+self.regNum(reg))
-
- def decVar(self,var):
- offset = len(self.stack)*4 - var.offset
-
- if -128 <= offset <= 127:
- return self.opcodes['']['decVarb'] % (offset & 0xff)
- return self.opcodes['']['decVarl'] % struct.pack('<l',offset)
-
- def dec(self, operator):
- if self.is_register(operator):
- return self.decReg(operator)
- if self.is_variable(operator):
- return self.decVar(operator)
- raise Exception, ('decrementing (%s) not yet implemented' % operator)
-
- def getValue(self,reg):
- return self.opcodes[reg]['value']
-
- def setValue(self,reg,value):
- self.opcodes[reg]['value'] = value
-
- def findMatch(self,value):
- # find exact match
- for i in self.registers():
- if self.getValue(i) == value:
- return i
- return None
-
- def popReg(self, reg):
- return '%c' % (0x58+self.regNum(reg))
-
- def pop(self, operator):
- self.unpush(1)
- if self.is_register(operator):
- return self.popReg(operator)
- raise Exception, ('popping non registers (%s) not yet implemented' % value)
-
- def pushReg(self, reg):
- return '%c' % (0x50+self.regNum(reg))
-
- def pushVariable(self, var):
- offset = len(self.stack)*4 - var.offset - 4
-
- if -128 <= offset <= 127:
- return self.opcodes['']['pushVarb'] % (offset & 0xff)
- return self.opcodes['']['pushVarl'] % struct.pack('<l',offset)
-
- def pushVarPtr(self, ptr):
- offset = len(self.stack)*4 - int(ptr[3:]) - 4
-
- if not offset:
- return self.push('esp')
- if -128 <= offset <= 127:
- return self.opcodes['']['pushVarPtrb'] % (offset & 0xff)
- return self.opcodes['']['pushVarPtrl'] % struct.pack('<l',offset)
-
- def pushTuple(self, tuple, notForTemps = ()):
- code = ''
- temps = self.registers()[:]
- to_push = [0]*len(tuple)
- for r in tuple+notForTemps:
- # first pass, removed the used registers from the possible temp regs
- if r in temps: temps.remove(r)
-
- # second pass, mov string or tupples into registers
- for i in range(len(tuple)):
- arg = tuple[i]
- if not (self.is_value(arg) or self.is_register(arg) or self.is_variable(arg)):
- # either it's a tupple or a string
- arg = temps[0]
- del temps[0]
- code += self.set(arg, tuple[i])
- to_push[i] = arg
-
- # third pass, just push arguments
- for i in range(len(to_push)-1,-1,-1):
- code += self.push(to_push[i])
-
- return code
-
- def pushString(self, string):
- answer = ''
- string += '\x00\x00\x00\x00'[:4-(len(string) % 4)]
- for i in struct.unpack('<%dl' % (len(string)/4), string):
- answer = self.push(i)+answer
- return answer
-
- def push(self,value, notForTemps = ()):
- self.stack.append(value)
-
- if self.is_register(value):
- return self.pushReg(value)
-
- if self.is_value(value):
- # find register with the same value
- match = self.findMatch(value)
- if match: return self.pushReg(match)
-
- if -0x80 <= value < 0x7f:
- return self.opcodes['']['pushb'] % (value & 0xff)
-
- return self.opcodes['']['pushl'] % struct.pack('<L',value)
-
- if self.is_tuple(value):
- self.unpush(1)
- return self.pushTuple(value, notForTemps = notForTemps)
-
- if self.is_variable(value):
- return self.pushVariable(value)
-
- if self.is_varpointer(value):
- return self.pushVarPtr(value)
-
- self.unpush(1)
- return self.pushString(value)
-
- def varAtTop(self, size = 4):
- return Variable(len(self.stack)*4, size)
-
- def alloc(self,bytes):
- # will allocate from stack and return a var
-
- words = (bytes + 3) / 4
-
- if not words: return ''
-
- self.stack.extend([None] * words)
- bytes = words * 4
-
- b = '%c' % (bytes & 0xff)
- l = struct.pack('<l',bytes)
-
- if -128 <= bytes <= 127:
- code = self.opcodes['esp']['subb'] % vars()
- else:
- code = self.opcodes['esp']['subl'] % vars()
-
- return (code, self.varAtTop(bytes))
-
- def freeVar(self,var):
-
- offset = len(self.stack)*4 - var.offset
-
- b = '%c' % (offset & 0xff)
- l = struct.pack('<l',offset)
-
- if -128 <= offset <= 127:
- return self.opcodes['esp']['subVarb'] % vars()
- else:
- return self.opcodes['esp']['subVarl'] % vars()
-
- def unpush(self, words):
- del self.stack[-words:]
-
- def free(self,bytes):
- # will free some bytes from the top of the stack
- # it's blind to stack's contents
- if self.is_value(bytes):
- words = (bytes + 3) / 4
- else:
- return self.freeVar(bytes)
-
- if not words: return ''
-
- self.unpush(words)
- bytes = -words * 4
-
- b = '%c' % (bytes & 0xff)
- l = struct.pack('<l',bytes)
-
- if -128 <= bytes <= 127:
- code = self.opcodes['esp']['subb'] % vars()
- else:
- code = self.opcodes['esp']['subl'] % vars()
-
- return code
-
- def save(self,reg):
- return (self.push(reg), self.varAtTop())
-
- def setReg(self,dest,src):
- if self.getValue(src) != None and self.getValue(src) == self.getValue(dest):
- return ''
-
- self.setValue(dest,self.getValue(src))
- return self.opcodes[dest]['mov'+src]
-
- def setVar(self,reg,var):
-
- self.setValue(reg,var)
-
- offset = len(self.stack)*4 - var.offset
-
- b = '%c' % (offset & 0xff)
- l = struct.pack('<l',offset)
-
- if -128 <= offset <= 127:
- return self.opcodes[reg]['movVarb'] % vars()
- else:
- return self.opcodes[reg]['movVarl'] % vars()
-
- def setVarPtr(self,reg,offset):
- self.setValue(reg,offset)
-
- offset = int(offset[3:])
- offset = len(self.stack)*4 - offset
-
- if not offset:
- return self.opcodes[reg]['movesp']
-
- b = '%c' % (offset & 0xff)
- l = struct.pack('<l',offset)
-
- if -128 <= offset <= 127:
- return self.opcodes[reg]['movVarPtrb'] % vars()
- else:
- return self.opcodes[reg]['movVarPtrl'] % vars()
-
- """
- This is not working, because it calls micro.set('ptrXX','register')
-
- def setTuple(self,reg,tuple):
- code,buf = self.alloc(len(tuple)*4)
- for i in range(len(tuple)):
- code += self.set(reg,tuple[i])
- code += self.set((buf+i*4).addr(),reg)
- code += self.set(reg,buf.addr())
- return code
- """
-
- def setString(self,reg,string):
- answer = self.set(reg,'esp')
- answer = self.push(string)+answer
- return answer
-
- def set(self,reg,newValue):
-
- value = self.getValue(reg)
-
- if value == newValue:
- return ''
-
- # find another register with the same value
- match = self.findMatch(newValue)
- if match: return self.setReg(reg,match)
-
- if not self.is_value(newValue):
- # if int() fails, then newValue is a string
- if self.is_register(newValue):
- # moving from a register
- return self.setReg(reg,newValue)
- else:
- # setting a tuple or list
- if self.is_tuple(newValue):
- return self.setTuple(reg,newValue)
-
- # setting a Variable or pointer to Variable
- if self.is_variable(newValue):
- return self.setVar(reg,newValue)
- if self.is_varpointer(newValue):
- return self.setVarPtr(reg,newValue)
-
- # setting a litteral string
- return self.setString(reg,newValue)
-
- if newValue == 0: # even if other reg is zero:
- return self.zero(reg) # xor has 2 bytes as well as mov reg,reg
-
- b = '%c' % (newValue & 0xff)
- w = struct.pack('<h',newValue & 0xffff)
- l = struct.pack('<L',newValue)
-
- opcodes = self.opcodes[reg]
- answer = None
-
- # if current value is a number
- if self.is_value(value) and (newValue & ~0xff) == (value & ~0xff) and opcodes['movb']:
- answer = opcodes['movb'] % vars()
-
- elif self.is_value(value) and (newValue & ~0xffff) == (value & ~0xffff):
- answer = opcodes['movw'] % vars()
- else:
- if (0 <= newValue < 0x100):
- answer = self.push(newValue)+self.pop(reg)
- elif 0x100 <= newValue < 0x10000:
- answer = self.zero(reg)+self.set(reg,newValue)
-
- self.setValue(reg,newValue)
- if answer:
- return answer
- else:
- return opcodes['movl'] % vars()
-
- # comparitions
- def cmpReg(self,left,right):
- # if self.getValue(src) != None and self.getValue(src) == self.getValue(dest):
- # return ''
- #
- return self.opcodes[left]['cmp'+right]
-
- def cmpValue(self, reg, value):
- # if self.getValue(reg) == value:
- # return ''
- b = '%c' % (value & 0xff)
- l = struct.pack('<L',value)
-
- if (-0x80 <= value < 0x7f):
- return self.opcodes[reg]['cmpb'] % vars()
-
- return self.opcodes[reg]['cmpl'] % vars()
-
- def cmpRegVar(self, reg, var):
- # compares a register and a variable
- raise Exception, "Not implemented yet"
-
- def cmpVarValue(self, var, value):
- # compares a variable with an immediate value
- if -128 <= value <= 127:
- # the value is a byte
- key = 'cmpb'
- value &= 0xff
- else:
- key = 'cmpl'
- value = struct.pack('<l',value)
-
- offset = len(self.stack)*4 - var.offset
-
- if -128 <= offset <= 127:
- # variable's offset is a byte
- return self.opcodes[''][key+'Varb'] % (offset & 0xff, value)
- else:
- return self.opcodes[''][key+'Varl'] % (struct.pack('<l', offset), value)
-
-
- def cmp(self, left, right):
- if self.is_register(left):
- if self.is_value(right):
- return self.cmpValue(left,right)
- if self.is_register(right):
- return self.cmpReg(left,right)
- if self.is_variable(right):
- return self.cmpReg(left,right)
- else:
- if self.is_value(right):
- return self.cmpVarValue(left,right)
- # the problem with this is that an if(var, reg) must have the oposite condition
- # if self.is_register(right):
- # return self.cmpRegVar(right,left)
-
- raise Exception, "Invalid comparision between %s and %s" % (left, right)
-
- # jumps
- def jumpRel(self,delta,condition = ''):
- # the jump is relative to the first byte of the jump
-
- b = '%c' % (delta - 2 & 0xff)
- l = struct.pack('<L',delta-5)
-
- if -128 < delta-2 < 127:
- return self.opcodes['']['jmpb'+condition] % vars()
- else:
- if condition:
- raise Exception, 'long conditional jumps not implementer yet'
- return self.opcodes['']['jmpl'] % vars()
-
- def opositeCondition(self, condition):
- return self.opcodes['']['!'+condition]
-
- def callVar(self, var):
- offset = len(self.stack)*4 - var.offset
-
- if -128 <= offset <= 127:
- # variable's offset is a byte
- return self.opcodes['']['callVarb'] % (offset & 0xff)
- else:
- return self.opcodes['']['callVarl'] % (struct.pack('<l', offset))
-
- def callRel(self,delta):
- # the jump is relative to the first byte of the jump
-
- return '\xe8'+(struct.pack('<l',delta-5))
-
- def jumpReg(self, reg):
- return '\xff%c' % (0xe0+self.regNum(reg))
-
- def callReg(self, reg):
- return '\xff%c' % (0xd0+self.regNum(reg))
-
- def call(self, dest):
- # XXX: next reset should not be reset but, for example,
- # when calling a function, the registers should be set
- # as left by the called function (some changed some not)
-
- self.reset()
- if self.is_value(dest):
- return self.callRel(dest)
- if self.is_variable(dest):
- return self.callVar(dest)
- if self.is_register(dest):
- return self.callReg(dest)
- raise Exception, ("Unsupported call type, calling (%s)" % dest)
-
- def ret(self,n = 0):
- if n:
- return '\xc2'+struct.pack('<h',n)
- else:
- return '\xc3'
-
- def regNum(self, reg):
- return self.registers().index(reg)
-
- # interactive utils
- def registers(self):
- return self._registers
-
- class Syscall:
- def __init__(self,micro):
- self.micro = micro
-
- def call(self, name, args = ()):
- code = self.setArgs(args)
- code += self.syscall(self.syscalls[name])
-
- return code, self.answer()
-
- class Linuxx86Syscall(Syscall):
- microClass = Microx86
- syscalls = {
- 'exit': 1,
- 'fork': 2,
- 'read': 3,
- 'write': 4,
- 'open': 5,
- 'close': 6,
- 'waitpid': 7,
- 'creat': 8,
- 'link': 9,
- 'unlink': 10,
- 'execve': 11,
- 'chdir': 12,
- 'time': 13,
- 'mknod': 14,
- 'chmod': 15,
- 'lchown': 16,
- 'break': 17,
- 'oldstat': 18,
- 'lseek': 19,
- 'getpid': 20,
- 'mount': 21,
- 'umount': 22,
- 'setuid': 23,
- 'getuid': 24,
- 'stime': 25,
- 'ptrace': 26,
- 'alarm': 27,
- 'oldfstat': 28,
- 'pause': 29,
- 'utime': 30,
- 'stty': 31,
- 'gtty': 32,
- 'access': 33,
- 'nice': 34,
- 'ftime': 35,
- 'sync': 36,
- 'kill': 37,
- 'rename': 38,
- 'mkdir': 39,
- 'rmdir': 40,
- 'dup': 41,
- 'pipe': 42,
- 'times': 43,
- 'prof': 44,
- 'brk': 45,
- 'setgid': 46,
- 'getgid': 47,
- 'signal': 48,
- 'geteuid': 49,
- 'getegid': 50,
- 'acct': 51,
- 'umount2': 52,
- 'lock': 53,
- 'ioctl': 54,
- 'fcntl': 55,
- 'mpx': 56,
- 'setpgid': 57,
- 'ulimit': 58,
- 'oldolduname': 59,
- 'umask': 60,
- 'chroot': 61,
- 'ustat': 62,
- 'dup2': 63,
- 'getppid': 64,
- 'getpgrp': 65,
- 'setsid': 66,
- 'sigaction': 67,
- 'sgetmask': 68,
- 'ssetmask': 69,
- 'setreuid': 70,
- 'setregid': 71,
- 'sigsuspend': 72,
- 'sigpending': 73,
- 'sethostname': 74,
- 'setrlimit': 75,
- 'getrlimit': 76,
- 'getrusage': 77,
- 'gettimeofday': 78,
- 'settimeofday': 79,
- 'getgroups': 80,
- 'setgroups': 81,
- 'select': 82,
- 'symlink': 83,
- 'oldlstat': 84,
- 'readlink': 85,
- 'uselib': 86,
- 'swapon': 87,
- 'reboot': 88,
- 'readdir': 89,
- 'mmap': 90,
- 'munmap': 91,
- 'truncate': 92,
- 'ftruncate': 93,
- 'fchmod': 94,
- 'fchown': 95,
- 'getpriority': 96,
- 'setpriority': 97,
- 'profil': 98,
- 'statfs': 99,
- 'fstatfs': 100,
- 'ioperm': 101,
- 'socketcall': 102,
- 'syslog': 103,
- 'setitimer': 104,
- 'getitimer': 105,
- 'stat': 106,
- 'lstat': 107,
- 'fstat': 108,
- 'olduname': 109,
- 'iopl': 110,
- 'vhangup': 111,
- 'idle': 112,
- 'vm86old': 113,
- 'wait4': 114,
- 'swapoff': 115,
- 'sysinfo': 116,
- 'ipc': 117,
- 'fsync': 118,
- 'sigreturn': 119,
- 'clone': 120,
- 'setdomainname': 121,
- 'uname': 122,
- 'modify_ldt': 123,
- 'adjtimex': 124,
- 'mprotect': 125,
- 'sigprocmask': 126,
- 'create_module': 127,
- 'init_module': 128,
- 'delete_module': 129,
- 'get_kernel_syms': 130,
- 'quotactl': 131,
- 'getpgid': 132,
- 'fchdir': 133,
- 'bdflush': 134,
- 'sysfs': 135,
- 'personality': 136,
- 'afs_syscall': 137,
- 'setfsuid': 138,
- 'setfsgid': 139,
- '_llseek': 140,
- 'getdents': 141,
- '_newselect': 142,
- 'flock': 143,
- 'msync': 144,
- 'readv': 145,
- 'writev': 146,
- 'getsid': 147,
- 'fdatasync': 148,
- '_sysctl': 149,
- 'mlock': 150,
- 'munlock': 151,
- 'mlockall': 152,
- 'munlockall': 153,
- 'sched_setparam': 154,
- 'sched_getparam': 155,
- 'sched_setscheduler': 156,
- 'sched_getscheduler': 157,
- 'sched_yield': 158,
- 'sched_get_priority_max': 159,
- 'sched_get_priority_min': 160,
- 'sched_rr_get_interval': 161,
- 'nanosleep': 162,
- 'mremap': 163,
- 'setresuid': 164,
- 'getresuid': 165,
- 'vm86': 166,
- 'query_module': 167,
- 'poll': 168,
- 'nfsservctl': 169,
- 'setresgid': 170,
- 'getresgid': 171,
- 'prctl':172,
- 'rt_sigreturn': 173,
- 'rt_sigaction': 174,
- 'rt_sigprocmask': 175,
- 'rt_sigpending': 176,
- 'rt_sigtimedwait': 177,
- 'rt_sigqueueinfo': 178,
- 'rt_sigsuspend': 179,
- 'pread': 180,
- 'pwrite': 181,
- 'chown': 182,
- 'getcwd': 183,
- 'capget': 184,
- 'capset': 185,
- 'sigaltstack': 186,
- 'sendfile': 187,
- 'getpmsg': 188,
- 'putpmsg': 189,
- 'vfork': 190,
- 'ugetrlimit': 191,
- 'mmap2': 192,
- 'truncate64': 193,
- 'ftruncate64': 194,
- 'stat64': 195,
- 'lstat64': 196,
- 'fstat64': 197,
- 'lchown32': 198,
- 'getuid32': 199,
- 'getgid32': 200,
- 'geteuid32': 201,
- 'getegid32': 202,
- 'setreuid32': 203,
- 'setregid32': 204,
- 'getgroups32': 205,
- 'setgroups32': 206,
- 'fchown32': 207,
- 'setresuid32': 208,
- 'getresuid32': 209,
- 'setresgid32': 210,
- 'getresgid32': 211,
- 'chown32': 212,
- 'setuid32': 213,
- 'setgid32': 214,
- 'setfsuid32': 215,
- 'setfsgid32': 216,
- 'pivot_root': 217,
- 'mincore': 218,
- 'madvise': 219,
- 'madvise1': 219,
- 'getdents64': 220,
- 'fcntl64': 221,
- 'security': 223,
- 'gettid': 224,
- 'readahead': 225,
- 'setxattr': 226,
- 'lsetxattr': 227,
- 'fsetxattr': 228,
- 'getxattr': 229,
- 'lgetxattr': 230,
- 'fgetxattr': 231,
- 'listxattr': 232,
- 'llistxattr': 233,
- 'flistxattr': 234,
- 'removexattr': 235,
- 'lremovexattr': 236,
- 'fremovexattr': 237,
- 'tkill': 238,
- 'sendfile64': 239,
- 'futex': 240,
- 'sched_setaffinity': 241,
- 'sched_getaffinity': 242,
- 'set_thread_area ': 243,
- }
- # socket calls
- socketcalls= {
- 'socket': 1,
- 'bind': 2,
- 'connect': 3,
- 'listen': 4,
- 'accept': 5,
- 'getsockname': 6,
- 'getpeername': 7,
- 'socketpair': 8,
- 'send': 9,
- 'recv': 10,
- 'sendto': 11,
- 'recvfrom': 12,
- 'shutdown': 13,
- 'setsockopt': 14,
- 'getsockopt': 15,
- 'sendmsg': 16,
- 'recvmsg': 17
- }
-
- def __init__(self,micro):
- Syscall.__init__(self,micro)
- self.args = ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp']
-
- def setArg(self, argNumber, value):
- return self.micro.set(self.args[argNumber],value)
-
- def setArgs(self, args = ()):
- code = ''
- for i in range(len(args)):
- code += self.setArg(i+1,args[i])
-
- return code
-
- def call(self, name, args = ()):
- if self.socketcalls.has_key(name):
- return self.socketCall(name,args)
- else:
- return Syscall.call(self,name,args)
-
- def syscall(self, number):
- answer = self.setArg(0,number)+'\xcd\x80' # int $0x80
- self.micro.setValue(self.args[0],None)
- return answer
-
- def socketCall(self,name,args):
- code = ''
- code += self.micro.push(args)
- sysCode, answer = self.call('socketcall',
- (self.socketcalls[name],self.micro.varAtTop().addr()))
- code += sysCode
- code += self.micro.free(4*len(args))
- return code, answer
-
- def answer(self):
- return 'eax'
-
- class StackBasedSyscall(Syscall):
- def __init__(self,micro):
- self.micro = micro
-
- def setArgs(self, args = (), notForTemps = ()):
- return self.micro.push(args, notForTemps = notForTemps)
-
- def answer(self):
- return 'eax'
-
- class OpenBSDx86Syscall(StackBasedSyscall):
- microClass = Microx86
- syscalls = {
- 'syscall': 0,
- 'exit': 1,
- 'fork': 2,
- 'read': 3,
- 'write': 4,
- 'open': 5,
- 'close': 6,
- 'wait4': 7,
- 'link': 9,
- 'unlink': 10,
- 'chdir': 12,
- 'fchdir': 13,
- 'mknod': 14,
- 'chmod': 15,
- 'chown': 16,
- 'break': 17,
- 'ogetfsstat': 18,
- 'getpid': 20,
- 'mount': 21,
- 'unmount': 22,
- 'setuid': 23,
- 'getuid': 24,
- 'geteuid': 25,
- 'ptrace': 26,
- 'recvmsg': 27,
- 'sendmsg': 28,
- 'recvfrom': 29,
- 'accept': 30,
- 'getpeername': 31,
- 'getsockname': 32,
- 'access': 33,
- 'chflags': 34,
- 'fchflags': 35,
- 'sync': 36,
- 'kill': 37,
- 'getppid': 39,
- 'dup': 41,
- 'opipe': 42,
- 'getegid': 43,
- 'profil': 44,
- 'ktrace': 45,
- 'sigaction': 46,
- 'getgid': 47,
- 'sigprocmask': 48,
- 'getlogin': 49,
- 'setlogin': 50,
- 'acct': 51,
- 'sigpending': 52,
- 'sigaltstack': 53,
- 'ioctl': 54,
- 'reboot': 55,
- 'revoke': 56,
- 'symlink': 57,
- 'readlink': 58,
- 'execve': 59,
- 'umask': 60,
- 'chroot': 61,
- 'omsync': 65,
- 'vfork': 66,
- 'sbrk': 69,
- 'sstk': 70,
- 'vadvise': 72,
- 'munmap': 73,
- 'mprotect': 74,
- 'madvise': 75,
- 'mincore': 78,
- 'getgroups': 79,
- 'setgroups': 80,
- 'getpgrp': 81,
- 'setpgid': 82,
- 'setitimer': 83,
- 'swapon': 85,
- 'getitimer': 86,
- 'dup2': 90,
- 'fcntl': 92,
- 'select': 93,
- 'fsync': 95,
- 'setpriority': 96,
- 'socket': 97,
- 'connect': 98,
- 'getpriority': 100,
- 'sigreturn': 103,
- 'bind': 104,
- 'setsockopt': 105,
- 'listen': 106,
- 'sigsuspend': 111,
- 'gettimeofday': 116,
- 'getrusage': 117,
- 'getsockopt': 118,
- 'readv': 120,
- 'writev': 121,
- 'settimeofday': 122,
- 'fchown': 123,
- 'fchmod': 124,
- 'rename': 128,
- 'flock': 131,
- 'mkfifo': 132,
- 'sendto': 133,
- 'shutdown': 134,
- 'socketpair': 135,
- 'mkdir': 136,
- 'rmdir': 137,
- 'utimes': 138,
- 'adjtime': 140,
- 'setsid': 147,
- 'quotactl': 148,
- 'nfssvc': 155,
- 'ostatfs': 157,
- 'ofstatfs': 158,
- 'getfh': 161,
- 'sysarch': 165,
- 'pread': 173,
- 'pwrite': 174,
- 'ntp_gettime': 175,
- 'ntp_adjtime': 176,
- 'setgid': 181,
- 'setegid': 182,
- 'seteuid': 183,
- 'lfs_bmapv': 184,
- 'lfs_markv': 185,
- 'lfs_segclean': 186,
- 'lfs_segwait': 187,
- 'stat': 188,
- 'fstat': 189,
- 'lstat': 190,
- 'pathconf': 191,
- 'fpathconf': 192,
- 'swapctl': 193,
- 'getrlimit': 194,
- 'setrlimit': 195,
- 'getdirentries': 196,
- 'mmap': 197,
- '__syscall': 198,
- 'lseek': 199,
- 'truncate': 200,
- 'ftruncate': 201,
- '__sysctl': 202,
- 'mlock': 203,
- 'munlock': 204,
- 'undelete': 205,
- 'futimes': 206,
- 'getpgid': 207,
- 'xfspioctl': 208,
- '__osemctl': 220,
- 'semget': 221,
- 'semop': 222,
- 'omsgctl': 224,
- 'msgget': 225,
- 'msgsnd': 226,
- 'msgrcv': 227,
- 'shmat': 228,
- 'oshmctl': 229,
- 'shmdt': 230,
- 'shmget': 231,
- 'clock_gettime': 232,
- 'clock_settime': 233,
- 'clock_getres': 234,
- 'nanosleep': 240,
- 'minherit': 250,
- 'rfork': 251,
- 'poll': 252,
- 'issetugid': 253,
- 'lchown': 254,
- 'getsid': 255,
- 'msync': 256,
- '__semctl': 257,
- 'shmctl': 258,
- 'msgctl': 259,
- 'getfsstat': 260,
- 'statfs': 261,
- 'fstatfs': 262,
- 'pipe': 263,
- 'fhopen': 264,
- 'fhstat': 265,
- 'fhstatfs': 266,
- 'preadv': 267,
- 'pwritev': 268,
- 'kqueue': 269,
- 'kevent': 270,
- 'mlockall': 271,
- 'munlockall': 272,
- }
- def syscall(self, number):
- answer = self.micro.push('eax')
- answer += self.micro.set('eax',number)+'\xcd\x80' # int $0x80
- self.micro.setValue('eax',None)
- return answer
-
- class Solarisx86Syscall(StackBasedSyscall):
- microClass = Microx86
- syscalls = {
- 'syscall': 0,
- 'exit': 1,
- 'fork': 2,
- 'read': 3,
- 'write': 4,
- 'open': 5,
- 'close': 6,
- 'wait': 7,
- 'creat': 8,
- 'link': 9,
- 'unlink': 10,
- 'exec': 11,
- 'chdir': 12,
- 'time': 13,
- 'mknod': 14,
- 'chmod': 15,
- 'chown': 16,
- 'brk': 17,
- 'stat': 18,
- 'lseek': 19,
- 'getpid': 20,
- 'mount': 21,
- 'umount': 22,
- 'setuid': 23,
- 'getuid': 24,
- 'stime': 25,
- 'pcsample': 26,
- 'alarm': 27,
- 'fstat': 28,
- 'pause': 29,
- 'utime': 30,
- 'stty': 31,
- 'gtty': 32,
- 'access': 33,
- 'nice': 34,
- 'statfs': 35,
- 'sync': 36,
- 'kill': 37,
- 'fstatfs': 38,
- 'pgrpsys': 39,
- #
- # subcodes:
- # getpgrp() :: syscall(39,0)
- # setpgrp() :: syscall(39,1)
- # getsid(pid) :: syscall(39,2,pid)
- # setsid() :: syscall(39,3)
- # getpgid(pid) :: syscall(39,4,pid)
- # setpgid(pid,pgid) :: syscall(39,5,pid,pgid)
- #
- 'xenix': 40,
- #
- # subcodes:
- # syscall(40, code, ...)
- #
- 'dup': 41,
- 'pipe': 42,
- 'times': 43,
- 'profil': 44,
- 'plock': 45,
- 'setgid': 46,
- 'getgid': 47,
- 'signal': 48,
- #
- # subcodes:
- # signal(sig, f) :: signal(sig, f) ((sig&SIGNO_MASK) == sig)
- # sigset(sig, f) :: signal(sig|SIGDEFER, f)
- # sighold(sig) :: signal(sig|SIGHOLD)
- # sigrelse(sig) :: signal(sig|SIGRELSE)
- # sigignore(sig) :: signal(sig|SIGIGNORE)
- # sigpause(sig) :: signal(sig|SIGPAUSE)
- # see <sys/signal.h>
- #
- 'msgsys': 49,
- #
- # subcodes:
- # msgget(...) :: msgsys(0, ...)
- # msgctl(...) :: msgsys(1, ...)
- # msgrcv(...) :: msgsys(2, ...)
- # msgsnd(...) :: msgsys(3, ...)
- # msgids(...) :: msgsys(4, ...)
- # msgsnap(...) :: msgsys(5, ...)
- # see <sys/msg.h>
- #
- 'syssun': 50,
- 'sysi86': 50,
- #
- # subcodes:
- # syssun(code, ...)
- # see <sys/sys3b.h>
- #
- 'acct': 51,
- 'shmsys': 52,
- #
- # subcodes:
- # shmat (...) :: shmsys(0, ...)
- # shmctl(...) :: shmsys(1, ...)
- # shmdt (...) :: shmsys(2, ...)
- # shmget(...) :: shmsys(3, ...)
- # shmids(...) :: shmsys(4, ...)
- # see <sys/shm.h>
- #
- 'semsys': 53,
- #
- # subcodes:
- # semctl(...) :: semsys(0, ...)
- # semget(...) :: semsys(1, ...)
- # semop (...) :: semsys(2, ...)
- # semids(...) :: semsys(3, ...)
- # semtimedop(...) :: semsys(4, ...)
- # see <sys/sem.h>
- #
- 'ioctl': 54,
- 'uadmin': 55,
- # 56 reserved for exch()
- 'utssys': 57,
- #
- #subcodes (third argument):
- # uname(obuf) (obsolete) :: syscall(57, obuf, ign, 0)
- # subcode 1 unused
- # ustat(dev, obuf) :: syscall(57, obuf, dev, 2)
- # fusers(path, flags, obuf) :: syscall(57, path, flags, 3, obuf)
- # see <sys/utssys.h>
- #
- 'fdsync': 58,
- 'execve': 59,
- 'umask': 60,
- 'chroot': 61,
- 'fcntl': 62,
- 'ulimit': 63,
- # 64-69 reserved for UNIX PC
- 'tasksys': 70,
- #
- # subcodes:
- # settaskid(...) :: tasksys(0, ...)
- # gettaskid(...) :: tasksys(1, ...)
- # getprojid(...) :: tasksys(2, ...)
- #
- 'acctctl': 71,
- 'exacctsys': 72,
- #
- # subcodes:
- # getacct(...) :: exacct(0, ...)
- # putacct(...) :: exacct(1, ...)
- # wracct(...) :: exacct(2, ...)
- #
- 'reserved_73': 73, # 73 reserved
- 'reserved_74': 74, # 74 reserved
- 'reserved_75': 75, # 75 reserved
- 'reserved_76': 76, # 76 reserved
- 'reserved_77': 77, # 77 reserved
- 'reserved_78': 78, # 78 reserved
- 'rmdir': 79,
- 'mkdir': 80,
- 'getdents': 81,
- # 82 not used, was libattach
- # 83 not used, was libdetach
- 'sysfs': 84,
- #
- # subcodes:
- # sysfs(code, ...)
- # see <sys/fstyp.h>
- #
- 'getmsg': 85,
- 'putmsg': 86,
- 'poll': 87,
-
- 'lstat': 88,
- 'symlink': 89,
- 'readlink': 90,
- 'setgroups': 91,
- 'getgroups': 92,
- 'fchmod': 93,
- 'fchown': 94,
- 'sigprocmask': 95,
- 'sigsuspend': 96,
- 'sigaltstack': 97,
- 'sigaction': 98,
- 'sigpending': 99,
- #
- # subcodes:
- # subcode 0 unused
- # sigpending(...) :: syscall(99, 1, ...)
- # sigfillset(...) :: syscall(99, 2, ...)
- #
- 'context': 100,
- #
- # subcodes:
- # getcontext(...) :: syscall(100, 0, ...)
- # setcontext(...) :: syscall(100, 1, ...)
- #
- 'evsys': 101,
- 'evtrapret': 102,
- 'statvfs': 103,
- 'fstatvfs': 104,
- 'getloadavg': 105,
- 'nfssys': 106,
- 'waitsys': 107,
- 'sigsendsys': 108,
- 'hrtsys': 109,
- 'acancel': 110,
- 'async': 111,
- 'priocntlsys': 112,
- 'pathconf': 113,
- 'mincore': 114,
- 'mmap': 115,
- 'mprotect': 116,
- 'munmap': 117,
- 'fpathconf': 118,
- 'vfork': 119,
- 'fchdir': 120,
- 'readv': 121,
- 'writev': 122,
- 'xstat': 123,
- 'lxstat': 124,
- 'fxstat': 125,
- 'xmknod': 126,
- 'clocal': 127,
- 'setrlimit': 128,
- 'getrlimit': 129,
- 'lchown': 130,
- 'memcntl': 131,
- 'getpmsg': 132,
- 'putpmsg': 133,
- 'rename': 134,
- 'uname': 135,
- 'setegid': 136,
- 'sysconfig': 137,
- 'adjtime': 138,
- 'systeminfo': 139,
- 'seteuid': 141,
- 'vtrace': 142,
- 'fork1': 143,
- 'sigtimedwait': 144,
- 'lwp_info': 145,
- 'yield': 146,
- 'lwp_sema_wait': 147,
- 'lwp_sema_post': 148,
- 'lwp_sema_trywait': 149,
- 'corectl': 151,
- 'modctl': 152,
- 'fchroot': 153,
- 'utimes': 154,
- 'vhangup': 155,
- 'gettimeofday': 156,
- 'getitimer': 157,
- 'setitimer': 158,
- 'lwp_create': 159,
- 'lwp_exit': 160,
- 'lwp_suspend': 161,
- 'lwp_continue': 162,
- 'lwp_kill': 163,
- 'lwp_self': 164,
- 'lwp_setprivate': 165,
- 'lwp_getprivate': 166,
- 'lwp_wait': 167,
- 'lwp_mutex_wakeup': 168,
- 'lwp_mutex_lock': 169,
- 'lwp_cond_wait': 170,
- 'lwp_cond_signal': 171,
- 'lwp_cond_broadcast': 172,
- 'pread': 173,
- 'pwrite': 174,
- 'llseek': 175,
- 'inst_sync': 176,
- 'srmlimitsys': 177,
- 'kaio': 178,
- #
- # subcodes:
- # aioread(...) :: kaio(AIOREAD, ...)
- # aiowrite(...) :: kaio(AIOWRITE, ...)
- # aiowait(...) :: kaio(AIOWAIT, ...)
- # aiocancel(...) :: kaio(AIOCANCEL, ...)
- # aionotify() :: kaio(AIONOTIFY)
- # aioinit() :: kaio(AIOINIT)
- # aiostart() :: kaio(AIOSTART)
- # see <sys/aio.h>
- #
- 'cpc': 179,
- 'tsolsys': 184,
- 'acl': 185,
- 'auditsys': 186,
- 'processor_bind': 187,
- 'processor_info': 188,
- 'p_online': 189,
- 'sigqueue': 190,
- 'clock_gettime': 191,
- 'clock_settime': 192,
- 'clock_getres': 193,
- 'timer_create': 194,
- 'timer_delete': 195,
- 'timer_settime': 196,
- 'timer_gettime': 197,
- 'timer_getoverrun': 198,
- 'nanosleep': 199,
- 'facl': 200,
- 'door': 201,
- #
- # Door Subcodes:
- # 0 door_create
- # 1 door_revoke
- # 2 door_info
- # 3 door_call
- # 4 door_return
- #
- 'setreuid': 202,
- 'setregid': 203,
- 'install_utrap': 204,
- 'signotify': 205,
- 'schedctl': 206,
- 'pset': 207,
- 'sparc_utrap_install': 208,
- 'resolvepath': 209,
- 'signotifywait': 210,
- 'lwp_sigredirect': 211,
- 'lwp_alarm': 212,
- # system calls for large file ( > 2 gigabyte) support
- 'getdents64': 213,
- 'mmap64': 214,
- 'stat64': 215,
- 'lstat64': 216,
- 'fstat64': 217,
- 'statvfs64': 218,
- 'fstatvfs64': 219,
- 'setrlimit64': 220,
- 'getrlimit64': 221,
- 'pread64': 222,
- 'pwrite64': 223,
- 'creat64': 224,
- 'open64': 225,
- 'rpcsys': 226,
- 'socket': 230,
- 'socketpair': 231,
- 'bind': 232,
- 'listen': 233,
- 'accept': 234,
- 'connect': 235,
- 'shutdown': 236,
- 'recv': 237,
- 'recvfrom': 238,
- 'recvmsg': 239,
- 'send': 240,
- 'sendmsg': 241,
- 'sendto': 242,
- 'getpeername': 243,
- 'getsockname': 244,
- 'getsockopt': 245,
- 'setsockopt': 246,
- 'sockconfig': 247,
- #
- # NTP codes
- #
- 'ntp_gettime': 248,
- 'ntp_adjtime': 249,
- 'lwp_mutex_unlock': 250,
- 'lwp_mutex_trylock': 251,
- 'lwp_mutex_init': 252,
- 'cladm': 253,
- 'lwp_sigtimedwait': 254,
- 'umount2': 255,
- }
-
- def syscall(self, number):
- answer = self.micro.push('eax')
- answer += self.micro.set('eax',number)+'\x9a\x00\x00\x00\x00\x07\x00' # callf 07:00000000
- self.micro.setValue('eax',None)
- return answer
-
- class FreeBSDx86Syscall(OpenBSDx86Syscall):
- pass
-
- class InlineEgg:
- # base
-
- def __init__(self,syscallClass = None, microClass = None):
- if not syscallClass:
- raise Exception, "You need to build an InlineEgg with the SyscallClass as argument"
- self.code = ''
- if not microClass:
- self.micro = syscallClass.microClass()
- else:
- self.micro = microClass()
- self.syscall = syscallClass(self.micro)
- self.setBaseAddr(0)
-
- def setBaseAddr(self, addr):
- self.base_addr = addr
-
- def addCode(self,code):
- self.code += code
-
- def __str__(self):
- return self.getCode()
-
- def getCode(self):
- return self.code
-
- def __len__(self):
- return len(self.getCode())
-
- # system calls
- def _SysCall(self,name,args = ()):
- code,answer = self.syscall.call(name,args)
- self.addCode(code)
- return answer
-
- def setuid(self, uid):
- return self._SysCall('setuid',(uid,))
-
- def setgid(self, uid):
- return self._SysCall('setgid',(uid,))
-
- def exit(self, retVal = 0):
- return self._SysCall('exit',(retVal,))
-
- def fork(self):
- return self._SysCall('fork')
-
- def read(self,fd,buf,count):
- return self._SysCall('read',(fd,buf,count))
-
- def write(self,fd,buf,count):
- return self._SysCall('write',(fd,buf,count))
-
- def open(self,fileName,flags=0,mode=0):
- return self._SysCall('open',(fileName,flags,mode))
-
- def close(self,fd):
- return self._SysCall('close',(fd,))
-
- def execve(self,fileName,argv = 0,envp = 0):
- if self.micro.is_tuple(argv):
- argv = self.save(argv+(0,)).addr()
- if self.micro.is_tuple(envp):
- envp = self.save(envp+(0,)).addr()
- return self._SysCall('execve',(fileName,argv, envp))
-
- def ptrace(self,request,pid,addr = 0, data = 0):
- return self._SysCall('ptrace',(request,pid,addr,data))
-
- def mkdir(self, dir, mode = 0777):
- return self._SysCall('mkdir',(dir,mode))
-
- def chroot(self, dir):
- return self._SysCall('chroot',(dir,))
-
- def stat(self,fileName,statBuf):
- return self._SysCall('stat',(fileName,statBuf))
-
- def dup(self,fd):
- return self._SysCall('dup',(fd,))
-
- def dup2(self,fd1,fd2):
- return self._SysCall('dup2',(fd1,fd2))
-
- def fstat(self, fd, stat_buf):
- return self._SysCall('fstat',(fd, stat_buf))
-
- def signal(self,signal,action):
- return self._SysCall('signal',(signal,action))
-
- def kill(self, pid, signal):
- return self._SysCall('kill',(pid, signal))
-
- def sigaction(self,signal,action):
- print "Warning: this is not finished!"
- self.save(action)
- sigaction = self.micro.varAtTop().addr()
- self.alloc(4*4)
- self._SysCall('sigaction',(signal,sigaction,0,8))
- self.free(4*5)
-
- # mmap gets arguments on stack
- # def mmap(self,start,length,prot,flags,fd,offset):
- # return self._SysCall('mmap',(start,length,prot,flags,fd,offset))
-
- def munmap(self,start,length):
- return self._SysCall('munmap',(start,length))
-
- def ioctl(self,fd,request,arg):
- return self._SysCall('ioctl',(fd,request,arg))
-
- # socket
- def socket(self, domain, type,proto = 0):
- return self._SysCall('socket',(domain,type,proto))
-
- def socketpair(self, domain, type, protocol,answer):
- return self._SysCall('socketpair',(domain,type,protocol,answer))
-
- def make_sockaddr(self, addr, family, len=16):
- ipaddr = self.inet_addr(addr[0])
- port = struct.pack('!h',addr[1])
- family = struct.pack('<h',family)
- return '%s%s%s%s' % (family, port, ipaddr, '\x00'*(len-8))
-
- def inet_addr(self, ip):
- ipaddr = map(lambda x:int(x),ip.split('.'))
- ipaddr = apply(struct.pack,['BBBB']+ipaddr)
- return ipaddr
-
- def connect(self, sock, addr):
- # as socket.socket().connect(addr) addr is a pair: (ip_addr, port)
- sa = self.make_sockaddr(addr, 2)
- return self._SysCall('connect',(sock, sa, len(sa)))
-
- def bind(self, socket, addr):
- # as socket.socket().bind(addr) addr is a pair: (ip_addr, port)
- sa = self.make_sockaddr(addr, 2)
- return self._SysCall('bind',(socket, sa, len(sa)))
-
- def listen(self, sock, backlog):
- return self._SysCall('listen',(sock, backlog))
-
- def accept(self, sock, sa, salen):
- return self._SysCall('accept',(sock, sa, salen))
-
- def getpeername(self, socket, addr, lenp):
- answer = self._SysCall('getpeername',(socket,addr,lenp))
- return answer
-
- # language
-
- def save(self,value):
- save = self.micro.save(value)
- self.addCode(save[0])
- return save[1]
-
- def alloc(self,bytes):
- alloc = self.micro.alloc(bytes)
- self.addCode(alloc[0])
- return alloc[1]
-
- def free(self,bytes):
- self.addCode(self.micro.free(bytes))
-
- def freeStack(self):
- self.free(4*len(self.micro.stack))
-
- def pop(self,reg):
- self.addCode(self.micro.pop(reg))
-
- def While1(self):
- return While1InlineEgg(self)
-
- def While(self, left, condition, right):
- return WhileInlineEgg(self, left, condition, right)
-
- def Do(self):
- return DoInlineEgg(self)
-
- def Function(self):
- return FunctionInlineEgg(self)
-
- def call(self,function):
- if type(function) == types.IntType:
- code = self.micro.call(int(function)-len(self.code)-self.base_addr)
- else:
- code = self.micro.call(int(function.address[5:])-len(self.code))
- self.addCode(code)
-
- def label(self, delta = 0):
- return 'label%d' % (len(self.code)+delta)
-
- def jump(self,label,condition = ''):
- if type(label) == types.IntType:
- code = self.micro.jumpRel(int(label)-len(self.code)-self.base_addr)
- else:
- code = self.micro.jumpRel(int(label[5:])-len(self.code),condition)
- self.addCode(code)
-
- def If(self, left, condition, right):
- return IfInlineEgg(self, left, condition, right)
-
- def ret(self, n = 0):
- self.addCode(self.micro.ret(n))
-
- # utils
-
- def dumpBin(self, fileName):
- open(fileName,'w').write(self.getCode())
-
- def dumpS(self,fileName):
- f = open(fileName,'w')
- f.write("""
- .text
- .align 4
- .globl _start
- .type _start,@function
-
- _start:
- .byte """)
- bytes = struct.unpack('%db' % len(self.code), self.code)
- bytes = map(lambda x: '0x%02x' % (x & 0xff),bytes)
- bytes = ','.join(bytes)
- f.write(bytes+'\n')
- f.close()
-
- def dumpElf(self,fileName, base = 0x8048000):
- import exelib
- import os
-
- ei_osabi_mapping = {
- Linuxx86Syscall: exelib.ELFOSABI_SYSV,
- FreeBSDx86Syscall: exelib.ELFOSABI_FREEBSD,
- OpenBSDx86Syscall: exelib.ELFOSABI_OPENBSD,
- Solarisx86Syscall: exelib.ELFOSABI_SYSV,
- }
- elf = exelib.Elf32Program(ei_osabi_mapping[self.syscall.__class__])
- elf.setArch(elf.ARCH_I386)
- elf.addCode(self.code)
-
- p = elf.programTable[0]
- p.p_vaddr = base
- elf.header.e_entry = p.p_vaddr+elf.totalHeaderLength()
-
- f = open(fileName,'w')
- f.write(elf.bytes())
- f.close()
- os.chmod(fileName,0755)
-
- def dumpAOut(self,fileName):
- import exelib
- import os
- elf = exelib.AOutProgram()
- elf.setArch(elf.ARCH_I386)
- elf.addCode(self.code)
-
- f = open(fileName,'w')
- f.write(elf.bytes())
- f.close()
- os.chmod(fileName,0755)
-
- def dumpExe(self, fileName):
- import exelib
- exe = exelib.PEProgram()
- exe.addCode(self.code)
- f = open(fileName, "w")
- f.write(exe.bytes())
- f.close()
-
-
- # XXX: This classes still have problems saving/restoring/tracking registers
- # for example, If will not be careful enough with registers, and may
- # wronly assume a register is set to some value, after exiting the If
-
- class LanguageInlineEgg(InlineEgg):
- def __init__(self,outer):
- InlineEgg.__init__(self,outer.syscall.__class__,outer.micro.__class__)
- self.outer = outer
- self.original_stack_size = 0
- self.setBaseAddr(self.outer.base_addr+len(self.outer))
-
- def freeStack(self):
- self.free(4*(len(self.micro.stack)-self.original_stack_size))
-
- # private
- def stackFromOuter(self):
- # we need to copy the stack so variables declared outside the statement
- # can be accessed inside it
- self.micro.stack = self.outer.micro.stack
- self.original_stack_size = len(self.micro.stack)
-
- def codeFromOuter(self):
- # the initial size of code must match that of outer
- # so jumps and labels are coherent inside and outside
- self.code = '.'*len(self.outer.code)
-
-
- class While1InlineEgg(LanguageInlineEgg):
- def __init__(self,outer):
- LanguageInlineEgg.__init__(self,outer)
- self.stackFromOuter()
-
- def end(self):
- loop = self.outer.label()
- self.freeStack()
- self.outer.addCode(self.code)
- self.outer.jump(loop)
-
-
- class FunctionInlineEgg(LanguageInlineEgg):
- def __init__(self,outer):
- LanguageInlineEgg.__init__(self,outer)
-
- # only for recursion, and only possible this easy if
- # calls and jumps are relative
- self.address = self.label()
-
- def end(self):
- self.freeStack()
- self.ret()
-
- real_size = len(self)
- self.jump(self.address)
- self.outer.jump(self.outer.label(len(self)))
- self.address = self.outer.label()
- self.outer.addCode(self.getCode()[:real_size])
-
- class IfInlineEgg(LanguageInlineEgg):
- def __init__(self,outer, left, condition, right):
- LanguageInlineEgg.__init__(self,outer)
- self.condition = condition
- if left:
- outer.addCode(outer.micro.cmp(left, right))
- self.top_label = self.label()
- self.stackFromOuter()
-
- def end(self):
- self.freeStack()
-
- real_size = len(self)
- self.jump(self.top_label,self.micro.opositeCondition(self.condition))
- self.outer.jump(self.outer.label(len(self)),self.micro.opositeCondition(self.condition))
- self.outer.addCode(self.getCode()[:real_size])
-
- class WhileInlineEgg(LanguageInlineEgg):
- def __init__(self,outer, left, condition, right):
- LanguageInlineEgg.__init__(self,outer)
- self.condition = condition
-
- self.top_label = self.label()
- self.loop = self.outer.label()
- self.outer.addCode(outer.micro.cmp(left, right))
- self.stackFromOuter()
-
- def end(self):
- self.freeStack()
-
- real_size = len(self)
- self.jump(self.top_label,self.micro.opositeCondition(self.condition))
- self.jump(self.top_label)
- self.outer.jump(self.outer.label(len(self)),self.micro.opositeCondition(self.condition))
- self.outer.addCode(self.getCode()[:real_size])
- self.outer.jump(self.loop)
-
- class DoInlineEgg(LanguageInlineEgg):
- def __init__(self,outer):
- LanguageInlineEgg.__init__(self,outer)
-
- self.loop = self.outer.label()
- self.stackFromOuter()
-
- def While(self, left, condition, right):
- self.freeStack()
- self.outer.addCode(self.code)
- self.outer.addCode(self.micro.cmp(left, right))
- self.outer.jump(self.loop,condition)
-